home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2006 November
/
PCWorld_2006-11_cd.bin
/
domacnost a kancelar
/
findgraph
/
fgraph.exe
/
{app}
/
TestVC
/
CoolMenu.cpp
next >
Wrap
C/C++ Source or Header
|
2002-08-09
|
24KB
|
806 lines
////////////////////////////////////////////////////////////////
// 1998 Microsoft Systems Journal.
// from DiLascia Coolmenu\MBTest\CoolMenu.cpp
//
#include "StdAfx.h"
#include "CoolMenu.h"
#include "Resource.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// helpers -----------------------------------------------------------------------
void PLFillRect(CDC& dc, const CRect& rc, COLORREF color);
void PLDrawEmbossed(CDC& dc, CImageList& il, int i, CPoint p, BOOL bColor=FALSE);
////////////////////////////////////////////////////////////////
// Helper functions
//
void PLFillRect(CDC& dc, const CRect& rc, COLORREF color)
{
CBrush brush(color);
CBrush* pOldBrush = dc.SelectObject(&brush);
dc.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATCOPY);
dc.SelectObject(pOldBrush);
}
// This is the magic ROP code used to generate the embossed look for
// a disabled button. It's listed in Appendix F of the Win32 Programmer's
// Reference as PSDPxax (!) which is a cryptic reverse-polish notation for
//
// ((Destination XOR Pattern) AND Source) XOR Pattern
//
// which I leave to you to figure out. In the case where I apply it,
// Source is a monochrome bitmap which I want to draw in such a way that
// the black pixels get transformed to the brush color and the white pixels
// draw transparently--i.e. leave the Destination alone.
//
// black ==> Pattern (brush)
// white ==> Destintation (ie, transparent)
//
// 0xb8074a is the ROP code that does this. For more info, see Charles
// Petzold, _Programming Windows_, 2nd Edition, p 622-624.
//
#define TRANSPARENTROP 0xb8074a
//////////////////
// Draw an image with the embossed (disabled) look.
//
// dc device context to draw in
// il image list containing image
// i index of image to draw
// p point in dc to draw image at
// bColor do color embossing. Default is B/W.
//
void PLDrawEmbossed(CDC& dc, CImageList& il, int i,
CPoint p, BOOL bColor)
{
IMAGEINFO info;
VERIFY(il.GetImageInfo(0, &info));
CRect rc = info.rcImage;
int cx = rc.Width();
int cy = rc.Height();
// create memory dc
CDC memdc;
memdc.CreateCompatibleDC(&dc);
// create mono or color bitmap
CBitmap bm;
if (bColor)
bm.CreateCompatibleBitmap(&dc, cx, cy);
else
bm.CreateBitmap(cx, cy, 1, 1, NULL);
// draw image into memory DC--fill BG white first
CBitmap* pOldBitmap = memdc.SelectObject(&bm);
memdc.PatBlt(0, 0, cx, cy, WHITENESS);
il.Draw(&memdc, i, CPoint(0,0), ILD_TRANSPARENT);
// This seems to be required. Why, I don't know. ???
COLORREF colorOldBG = dc.SetBkColor(RGB(255,255,255)); // white
// Draw using hilite offset by (1,1), then shadow
CBrush brShadow(GetSysColor(COLOR_3DSHADOW));
CBrush brHilite(GetSysColor(COLOR_3DHIGHLIGHT));
CBrush* pOldBrush = dc.SelectObject(&brHilite);
dc.BitBlt(p.x+1, p.y+1, cx, cy, &memdc, 0, 0, TRANSPARENTROP);
dc.SelectObject(&brShadow);
dc.BitBlt(p.x, p.y, cx, cy, &memdc, 0, 0, TRANSPARENTROP);
dc.SelectObject(pOldBrush);
dc.SetBkColor(colorOldBG); // restore
memdc.SelectObject(pOldBitmap); // ...
}
// constants used for drawing-----------------------------------------------------------------------
const CXGAP = 1; // num pixels between button and text
const CXTEXTMARGIN = 2; // num pixels after hilite to start text
const CXBUTTONMARGIN = 2; // num pixels wider button is than bitmap
const CYBUTTONMARGIN = 2; // ditto for height
// DrawText flags
const DT_MYSTANDARD = DT_SINGLELINE|DT_LEFT|DT_VCENTER;
// identifies owner-draw data as mine
const LONG MYITEMIDM = MAKELONG(MAKEWORD('m','i'),MAKEWORD('m','0'));
const LONG MYITEMIDD = MAKELONG(MAKEWORD('m','i'),MAKEWORD('d','0'));
// private struct: one of these for each owner-draw menu item
struct CMyItemData {
long magicNum; // magic number identifying me
CString text; // item text
UINT fType; // original item type flags
int iButton; // index of button image in image list
CMyItemData() { magicNum = MYITEMIDM; }
BOOL IsMyItemData() { return magicNum == MYITEMIDM; }
};
// private struct: one of these for dropdown buttons WM_NOTIFY
struct CMyDropData {
UINT idMenu; // idr popup menu
UINT uFlags; // default TPM_RIGHTBUTTON
long magicNum; // magic number identifying me
CMyDropData() { magicNum = MYITEMIDD; }
BOOL IsMyDropData() { return magicNum == MYITEMIDD; }
};
IMPLEMENT_DYNAMIC(CCoolMenuManager, CSubclassWnd)
CCoolMenuManager::CCoolMenuManager()
{
m_szButton =CSize(18,18); // will compute later
}
CCoolMenuManager::~CCoolMenuManager()
{
Destroy();
}
//////////////////
// Destroy everything. Called from destructor
//
void CCoolMenuManager::Destroy()
{
m_fontMenu.DeleteObject();
//TRACE0("ConvertMenuRemove \n");
while (!m_menuItems.IsEmpty())
{
CMyItemData *pmd = (CMyItemData *)m_menuItems.RemoveHead();
// TRACE1("delete = %s \n",pmd->text);
delete pmd;
}
// iterating all (key, value) pairs
POSITION pos = m_dropButns.GetStartPosition();
while (pos!=NULL)
{
CMyDropData *pdd;
WORD wKey;
m_dropButns.GetNextAssoc(pos, wKey, (void *&)pdd);
delete pdd;
// TRACE1("id=%d \n",wKey);
}
m_dropButns.RemoveAll();
}
//////////////////
// Call this to install the menu manager. Install(NULL) to un-install.
//
void CCoolMenuManager::Install(CFrameWnd* pFrame, CToolBar *pToolBar)
{
ASSERT_VALID(pFrame);
m_pFrame = pFrame;
m_pToolBar = pToolBar;
AddDropDown(ID_FILE_OPEN, IDR_FILEDROPDOWN, TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_VERTICAL);
HookWindow(pFrame); // install message hook
}
//////////////////
// Call this to add drop down style buttons
//
void CCoolMenuManager::AddDropDown(UINT idButton, UINT idMenu, UINT uFlags)
{
m_pToolBar->GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS);
TBBUTTONINFO tbi;
tbi.dwMask= TBIF_STYLE;
tbi.cbSize= sizeof(TBBUTTONINFO);
m_pToolBar->GetToolBarCtrl().GetButtonInfo(idButton, &tbi);
tbi.fsStyle |= TBSTYLE_DROPDOWN;
m_pToolBar->GetToolBarCtrl().SetButtonInfo(idButton, &tbi);
CMyDropData *pdd;
pdd = new CMyDropData; // create one
pdd->idMenu = idMenu;
pdd->uFlags = uFlags;
m_dropButns.SetAt(idButton, pdd);
}
/////////////////////////////////////////////////////////////////////////////////////
//////////////////
// Get menu font, creating if needed
//
CFont* CCoolMenuManager::GetMenuFont()
{
if (!(HFONT)m_fontMenu) {
NONCLIENTMETRICS info;
info.cbSize = sizeof(info);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
VERIFY(m_fontMenu.CreateFontIndirect(&info.lfMenuFont));
}
return &m_fontMenu;
}
// Helper function to draw justified menu text. If the text contains a TAB,
// draw everything after the tab right-aligned
//
void CCoolMenuManager::DrawMenuText(CDC& dc, CRect rc, CString text,
COLORREF color)
{
CString left = text;
CString right;
int iTabPos = left.Find('\t');
if (iTabPos >= 0) {
right = left.Right(left.GetLength() - iTabPos - 1);
left = left.Left(iTabPos);
}
dc.SetTextColor(color);
dc.DrawText(left, &rc, DT_MYSTANDARD);
if (iTabPos > 0)
dc.DrawText(right, &rc, DT_MYSTANDARD|DT_RIGHT);
}
#ifndef OBM_CHECK
#define OBM_CHECK 32760 // from winuser.h
#endif
//////////////////
// Draw 3D checkmark
//
// dc device context to draw in
// rc rectangle to center bitmap in
// bSelected TRUE if button is also selected
// hbmCheck Checkmark bitmap to use, or NULL for default
//
BOOL CCoolMenuManager::Draw3DCheckmark(CDC& dc, const CRect& rc,
BOOL bSelected, HBITMAP hbmCheck)
{
// get checkmark bitmap if none, use Windows standard
if (!hbmCheck) {
CBitmap bm;
VERIFY(bm.LoadOEMBitmap(OBM_CHECK));
hbmCheck = (HBITMAP)bm.Detach();
ASSERT(hbmCheck);
}
// center bitmap in caller's rectangle
BITMAP bm;
::GetObject(hbmCheck, sizeof(bm), &bm);
int cx = bm.bmWidth;
int cy = bm.bmHeight;
CRect rcDest = rc;
CPoint p(0,0);
CSize delta(CPoint((rc.Width() - cx)/2, (rc.Height() - cy)/2));
if (rc.Width() > cx)
rcDest = CRect(rc.TopLeft() + delta, CSize(cx, cy));
else
p -= delta;
// select checkmark into memory DC
CDC memdc;
memdc.CreateCompatibleDC(&dc);
HBITMAP hOldBM = (HBITMAP)::SelectObject(memdc, hbmCheck);
// set BG color based on selected state
COLORREF colorOld =
dc.SetBkColor(GetSysColor(bSelected ? COLOR_MENU : COLOR_3DLIGHT));
dc.BitBlt(rcDest.left, rcDest.top, rcDest.Width(), rcDest.Height(),
&memdc, p.x, p.y, SRCCOPY);
dc.SetBkColor(colorOld);
::SelectObject(memdc, hOldBM); // restore
// draw pushed-in hilight.
if (rc.Width() > cx) // if room:
rcDest.InflateRect(1,1); // inflate checkmark by one pixel all around
dc.DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);
return TRUE;
}
//////////////////
// Draw button form toolbar
//
// dc device context to draw in
// iButton number in m_wndToolBar
// p start point
// bEnabled TRUE if button is not disabled
//
void CCoolMenuManager::DrawButton(CDC& dc, int iButton, CPoint p, BOOL bEnabled)
{
TBBUTTON butn;
if (m_pToolBar->GetToolBarCtrl().GetButton(iButton, &butn))
{
CImageList *ImageList = m_pToolBar->GetToolBarCtrl().GetImageList();
if (bEnabled)
ImageList->Draw(&dc, butn.iBitmap, p, ILD_TRANSPARENT);
else
{
HICON hIcon = ImageList->ExtractIcon(butn.iBitmap);
ASSERT(hIcon);
dc.DrawState(p, CSize(0,0), hIcon, DSS_DISABLED, (HBRUSH)NULL);
DestroyIcon(hIcon);
// or use DrawEmbossed to draw disabeld button, w/color flag
// PLDrawEmbossed(dc, *ImageList, butn.iBitmap, p, true);
}
}
}
//-----------------------------------------------------------------------------------
//////////////////
// Handle WM_MEASUREITEM on behalf of frame: compute menu item size.
//
BOOL CCoolMenuManager::OnMeasureItem(LPMEASUREITEMSTRUCT lpms)
{
ASSERT(lpms);
CMyItemData* pmd = (CMyItemData*)lpms->itemData;
ASSERT(pmd);
if (lpms->CtlType != ODT_MENU || !pmd->IsMyItemData())
return FALSE; // not handled by me
if (pmd->fType & MFT_SEPARATOR)
{
// separator: use half system height and zero width
lpms->itemHeight = GetSystemMetrics(SM_CYMENU)>>1;
lpms->itemWidth = 0;
} else
{
// compute size of text: use DrawText with DT_CALCRECT
CString text = pmd->text;
CWindowDC dc(NULL); // screen DC--I won't actually draw on it
CRect rcText(0,0,0,0);
CFont* pOldFont = dc.SelectObject(GetMenuFont());
dc.DrawText(text, rcText, DT_MYSTANDARD|DT_CALCRECT);
dc.SelectObject(pOldFont);
// height of item is just height of a standard menu item
lpms->itemHeight= max(GetSystemMetrics(SM_CYMENU), rcText.Height());
// width is width of text plus a bunch of stuff
int cx = rcText.Width(); // text width
cx += CXTEXTMARGIN<<1; // L/R margin for readability
cx += CXGAP; // space between button and menu text
cx += m_szButton.cx<<1; // button width (L=button; R=empty margin)
// whatever value I return in lpms->itemWidth, Windows will add the
// width of a menu checkmark, so I must subtract to defeat Windows. Argh.
//
cx -= GetSystemMetrics(SM_CXMENUCHECK)-1;
lpms->itemWidth = cx; // done deal
//TRACE1(_T("OnMeasureItem for '%s':"), text); TRACE2(_T("\tw=%d h=%d\n"), lpms->itemWidth, lpms->itemHeight);
}
return TRUE;
}
/////////////////
// Handle WM_DRAWITEM on behalf of frame. Note: in all that goes
// below, can't assume rcItem.left=0 because of multi-column menus!
//
BOOL CCoolMenuManager::OnDrawItem(LPDRAWITEMSTRUCT lpds)
{
ASSERT(lpds);
CMyItemData* pmd = (CMyItemData*)lpds->itemData;
ASSERT(pmd);
if (lpds->CtlType != ODT_MENU || !pmd->IsMyItemData())
return FALSE; // not handled by me
ASSERT(lpds->itemAction != ODA_FOCUS);
ASSERT(lpds->hDC);
CDC dc;
dc.Attach(lpds->hDC);
const CRect& rcItem = lpds->rcItem;
if (pmd->fType & MFT_SEPARATOR)
{
// draw separator
CRect rc = rcItem; // copy rect
rc.top += rc.Height()>>1; // vertical center
dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP); // draw separator line
} else
{ // not a separator
CString text = pmd->text;
BOOL bDisabled = lpds->itemState & ODS_GRAYED;
BOOL bSelected = lpds->itemState & ODS_SELECTED;
BOOL bChecked = lpds->itemState & ODS_CHECKED;
BOOL bHaveButn=FALSE;
// Paint button, or blank if none
CRect rcButn(rcItem.TopLeft(), m_szButton); // button rect
rcButn += CPoint(0, // center vertically
(rcItem.Height() - rcButn.Height())>>1 );
int iButton = pmd->iButton;
//TRACE1("text=%s ",text);TRACE2("on draw: id=%d iButton=%d\n",lpds->itemID,iButton);
if (iButton >= 0)
{
// this item has a button!
bHaveButn = TRUE;
// compute point to start drawing
CSize sz = rcButn.Size() - m_szButton;
sz.cx >>= 1;
sz.cy >>= 1;
CPoint p(rcButn.TopLeft() + sz);
// draw disabled or normal
if (!bDisabled)
{
// normal: fill BG depending on state
PLFillRect(dc, rcButn, GetSysColor(
(bChecked && !bSelected) ? COLOR_3DLIGHT : COLOR_MENU));
// draw pushed-in or popped-out edge
if (bSelected || bChecked)
{
CRect rc2 = rcButn;
dc.DrawEdge(rc2, bChecked ? BDR_SUNKENOUTER : BDR_RAISEDINNER,
BF_RECT);
}
}
// draw the button!
DrawButton(dc, iButton, p, !bDisabled);
} else
{
// no button: look for custom checked/unchecked bitmaps
CMenuItemInfo info;
info.fMask = MIIM_CHECKMARKS;
GetMenuItemInfo((HMENU)lpds->hwndItem,
lpds->itemID, MF_BYCOMMAND, &info);
if (bChecked || info.hbmpUnchecked) {
bHaveButn = Draw3DCheckmark(dc, rcButn, bSelected,
bChecked ? info.hbmpChecked : info.hbmpUnchecked);
}
}
// Done with button, now paint text. First do background if needed.
int cxButn = m_szButton.cx; // width of button
COLORREF colorBG = GetSysColor(bSelected ? COLOR_HIGHLIGHT : COLOR_MENU);
if (bSelected || lpds->itemAction==ODA_SELECT)
{
// selected or selection state changed: paint text background
CRect rcBG = rcItem; // whole rectangle
if (bHaveButn) // if there's a button:
rcBG.left += cxButn + CXGAP; // don't paint over it!
PLFillRect(dc, rcBG, colorBG); // paint it!
}
// compute text rectangle and colors
CRect rcText = rcItem; // start w/whole item
rcText.left += cxButn + CXGAP + CXTEXTMARGIN; // left margin
rcText.right -= cxButn; // right margin
dc.SetBkMode(TRANSPARENT); // paint transparent text
COLORREF colorText = GetSysColor(bDisabled ? COLOR_GRAYTEXT :
bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT);
// Now paint menu item text. No need to select font,
// because windows sets it up before sending WM_DRAWITEM
//
if (bDisabled && (!bSelected || colorText == colorBG))
{
// disabled: draw hilite text shifted southeast 1 pixel for embossed
// look. Don't do it if item is selected, tho--unless text color same
// as menu highlight color. Got it?
//
DrawMenuText(dc, rcText + CPoint(1,1), text, GetSysColor(COLOR_3DHILIGHT));
}
DrawMenuText(dc, rcText, text, colorText); // finally!
}
dc.Detach();
return TRUE; // handled
}
//////////////////
// Handle WM_INITMENUPOPUP on behalf of frame.
//
void CCoolMenuManager::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)
{
ConvertMenu(pMenu, nIndex, bSysMenu, TRUE);
}
//////////////////
// Handle WM_MENUSELECT: check for menu closed
//
void CCoolMenuManager::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
{
if (hSysMenu==NULL && nFlags==0xFFFF) {
// Windows has closed the menu: restore all menus to original state
while (!m_menuList.IsEmpty()) {
ConvertMenu(CMenu::FromHandle((HMENU)m_menuList.RemoveHead()),
0, FALSE, FALSE);
}
}
}
//////////////////
// This rather gnarly function is used both to convert the menu from strings to
// owner-draw and vice versa. In either case, it also appends automagic
// accelerator key names to the menu items, if m_bAutoAccel is TRUE.
//
void CCoolMenuManager::ConvertMenu(CMenu* pMenu,
UINT nIndex, BOOL bSysMenu, BOOL bShowButtons)
{
ASSERT_VALID(pMenu);
CString sItemName;
UINT nItem = pMenu->GetMenuItemCount();
for (UINT i = 0; i < nItem; i++) // loop over each item in menu
{
// get menu item info
char itemname[256];
CMenuItemInfo info;
info.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_ID | MIIM_TYPE;
info.dwTypeData = itemname;
info.cch = sizeof(itemname);
::GetMenuItemInfo(*pMenu, i, TRUE, &info);
CMyItemData* pmd = (CMyItemData*)info.dwItemData;
if (pmd && !pmd->IsMyItemData())
{
TRACE0(_T("CCoolMenuManager: ignoring foreign owner-draw item\n"));
continue; // owner-draw menu item isn't mine--leave it alone
}
if (bSysMenu && info.wID >= 0xF000)
{
TRACE0(_T("CCoolMenuManager: ignoring sys menu item\n"));
continue; // don't do for system menu commands
}
// now that I have the info, I will modify it
info.fMask = 0; // assume nothing to change
if (bShowButtons)
{
// I'm showing buttons: convert to owner-draw
if (!(info.fType & MFT_OWNERDRAW))
{
// If not already owner-draw, make it so. NOTE: If app calls
// pCmdUI->SetText to change the text of a menu item, MFC will
// turn the item to MFT_STRING. So I must set it back to
// MFT_OWNERDRAW again. In this case, the menu item data (pmd)
// will still be there.
//
info.fType |= MFT_OWNERDRAW;
info.fMask |= MIIM_TYPE;
if (!pmd)
{ // if no item data:
pmd = new CMyItemData; // create one
ASSERT(pmd); // (I hope)
m_menuItems.AddTail(pmd);
pmd->fType = info.fType; // handy when drawing
pmd->iButton=m_pToolBar->CommandToIndex(info.wID);
//TRACE2(_T("new wId=%d %s \t"), info.wID, info.dwTypeData); TRACE1("nin=%d\n",++nin);
info.dwItemData = (DWORD)pmd; // set in menu item data
info.fMask |= MIIM_DATA; // set item data
}
pmd->text = info.dwTypeData; // copy menu item string
}
// now add the menu to list of "converted" menus
HMENU hmenu = pMenu->GetSafeHmenu();
ASSERT(hmenu);
if (!m_menuList.Find(hmenu))
m_menuList.AddHead(hmenu);
} else // !bShowButtons
{
// no buttons -- I'm converting to strings
if (info.fType & MFT_OWNERDRAW)
{ // if ownerdraw:
info.fType &= ~MFT_OWNERDRAW; // turn it off
info.fMask |= MIIM_TYPE; // change item type
ASSERT(pmd); // sanity check
sItemName = pmd->text; // save name before deleting pmd
} else // otherwise:
sItemName = info.dwTypeData; // use name from MENUITEMINFO
if (pmd)
{
// NOTE: pmd (item data) could still be left hanging around even
// if MFT_OWNERDRAW is not set, in case mentioned above where app
// calls pCmdUI->SetText to set text of item and MFC sets the type
// to MFT_STRING.
//
info.dwItemData = NULL; // item data is NULL
info.fMask |= MIIM_DATA; // change it
POSITION pos=m_menuItems.Find(pmd);
if (pos!=NULL)
m_menuItems.RemoveAt(pos);
delete pmd; // and item data too
//TRACE2(_T("delete wId=%d %s \t"), info.wID, sItemName); TRACE1("nin=%d\n",--nin);
}
if (info.fMask & MIIM_TYPE)
{
// if setting name, copy name from CString to buffer and set cch
strncpy(itemname, sItemName, sizeof(itemname));
info.dwTypeData = itemname;
info.cch = sItemName.GetLength();
}
}
// if after all the above, there is anything to change, change it
if (info.fMask)
{
//TRACE2(_T("Converting '%s' to %s\n"), itemname, (info.fType & MFT_OWNERDRAW) ? _T("OWNERDRAW") : _T("STRING"));
SetMenuItemInfo(*pMenu, i, TRUE, &info);
}
}
}
//////////////////
// Virtual CSubclassWnd window proc. All messages come here before frame
// window. Isn't it cool? Just like in the old days!
//
LRESULT CCoolMenuManager::WindowProc(UINT msg, WPARAM wp, LPARAM lp)
{
switch(msg)
{
case WM_MEASUREITEM:
if (OnMeasureItem((MEASUREITEMSTRUCT*)lp))
return TRUE; // handled
break;
case WM_DRAWITEM:
if (OnDrawItem((DRAWITEMSTRUCT*)lp))
return TRUE; // handled
break;
case WM_INITMENUPOPUP:
// Very important: must let frame window handle it first!
// Because if someone calls CCmdUI::SetText, MFC will change item to
// MFT_STRING, so I must change back to MFT_OWNERDRAW.
//
CSubclassWnd::WindowProc(msg, wp, lp);
OnInitMenuPopup(CMenu::FromHandle((HMENU)wp),
(UINT)LOWORD(lp), (BOOL)HIWORD(lp));
return 0;
case WM_MENUSELECT:
OnMenuSelect((UINT)LOWORD(wp), (UINT)HIWORD(wp), (HMENU)lp);
break;
case WM_NOTIFY:
OnNotify(msg, wp, lp);
break;
case WM_COMMAND:
{
UINT nId = LOWORD(wp);// GET_WM_COMMAND_ID(wParam,lParam);
switch ( nId )
{
case ID_FILEDROPDOWN: //-->> unused now
OnFiledropdown(nId);
break;
}
break;
}
}
return CSubclassWnd::WindowProc(msg, wp, lp);
}
BOOL CCoolMenuManager::OnNotify(UINT msg, WPARAM wParam, LPARAM lParam)
{
LPNMHDR lpnm = (LPNMHDR)lParam;
switch(lpnm->code)
{
case TBN_DROPDOWN:
{
RECT rc;
LPNMTOOLBAR lpnmTB =(LPNMTOOLBAR)lParam;
CMyDropData* pdd;
ASSERT(pdd);
if ( !m_dropButns.Lookup(lpnmTB->iItem, (void *&)pdd)
|| !pdd->IsMyDropData())
{
// TRACE2("idBut=%d idMenu=%d\n",lpnmTB->iItem, pdd->idMenu);
return FALSE; // not handled by me
}
SendMessage(lpnmTB->hdr.hwndFrom, TB_GETRECT,
(WPARAM)lpnmTB->iItem, (LPARAM)&rc);
MapWindowPoints(lpnmTB->hdr.hwndFrom, HWND_DESKTOP, (LPPOINT)&rc, 2);
CMenu bar;
if (bar.LoadMenu(pdd->idMenu))
{
CMenu& popup = *bar.GetSubMenu(0);
ASSERT(popup.m_hMenu != NULL);
popup.TrackPopupMenu(pdd->uFlags, rc.left, rc.bottom, AfxGetMainWnd());
}
/*
TPMPARAMS tpm;
tpm.cbSize = sizeof(TPMPARAMS);
tpm.rcExclude = rc;
hMenuLoaded = LoadMenu(g_hinst, MAKEINTRESOURCE(IDR_POPUP));
hPopupMenu = GetSubMenu(LoadMenu(g_hinst,
MAKEINTRESOURCE(IDR_POPUP)),0);
TrackPopupMenuEx(hPopupMenu,
TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL,
rc.left, rc.bottom, g_hwndMain, &tpm);
DestroyMenu(hMenuLoaded);
*/
}
return (FALSE);
}
return FALSE;
}
//-------------------------------------------------------------------------------
// ╧ε Ωφε∩Ωσ popup menu
// Unused now
void CCoolMenuManager::OnFiledropdown(UINT nIdButn)
{
UINT nIdMenu;
if (nIdButn == ID_FILEDROPDOWN)
nIdMenu = IDR_FILEDROPDOWN;
else return;
CRect rc;
m_pToolBar->GetToolBarCtrl().GetRect(nIdButn, &rc);
CPoint point(rc.left, rc.bottom+3);
m_pFrame->ClientToScreen(&point);
if (!m_pToolBar->SendMessage(TB_ISBUTTONCHECKED,(WPARAM)nIdButn,0))
{
CMenu bar;
if (bar.LoadMenu(nIdMenu))
{
m_pToolBar->SendMessage(TB_CHECKBUTTON,(WPARAM)nIdButn,(LPARAM)MAKELONG( TRUE,0));
CMenu& popup = *bar.GetSubMenu(0);
ASSERT(popup.m_hMenu != NULL);
popup.TrackPopupMenu(TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd());
}
}
m_pToolBar->SendMessage(TB_CHECKBUTTON,(WPARAM)nIdButn,(LPARAM)MAKELONG(FALSE,0));
}